package org.catspaw.cherubim.persistence.jpa;

import java.util.Collections;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.catspaw.cherubim.persistence.transaction.TransactionResourceLocal;

public class EntityManagerFactoryUtils {

	public static final String			DEFAULT_PERSISTENCE_UNIT_NAME	= "default";
	private static final String			ENTITY_MANAGER_KEY				= EntityManager.class.getName();
	private static String				persistenceUnitName				= DEFAULT_PERSISTENCE_UNIT_NAME;
	@SuppressWarnings("unchecked")
	private static Map<String, String>	properties						= Collections.EMPTY_MAP;

	private EntityManagerFactoryUtils() {
	}

	public static EntityManagerFactory getEntityManagerFactory() {
		return Holder.instance;
	}

	public static EntityManager getCurrentEntityManager() {
		EntityManager entityManager = (EntityManager) TransactionResourceLocal.getResource(ENTITY_MANAGER_KEY);
		if (entityManager == null) {
			entityManager = Holder.instance.createEntityManager();
			TransactionResourceLocal.bindResource(ENTITY_MANAGER_KEY, entityManager);
			return entityManager;
		} else if (!entityManager.isOpen()) {
			throw new IllegalStateException("the entityManager on current thread was closed");
		}
		return entityManager;
	}

	public static EntityManager createEntityManager() {
		return Holder.instance.createEntityManager();
	}

	public static void closeCurrentEntityManager() {
		EntityManager entityManager = (EntityManager) TransactionResourceLocal.getResource(ENTITY_MANAGER_KEY);
		TransactionResourceLocal.unbindResource(ENTITY_MANAGER_KEY);
		if (entityManager != null && entityManager.isOpen()) {
			entityManager.close();
		}
	}

	public static String getPersistenceUnitName() {
		return persistenceUnitName;
	}

	public static Map<String, String> getProperties() {
		return properties;
	}

	public static void setPersistenceUnitName(String persistenceUnitName) {
		EntityManagerFactoryUtils.persistenceUnitName = persistenceUnitName;
	}

	public static void setProperties(Map<String, String> properties) {
		EntityManagerFactoryUtils.properties = properties;
	}

	private static class Holder {

		private static final EntityManagerFactory	instance;
		static {
			instance = Persistence.createEntityManagerFactory(persistenceUnitName, properties);
		}
	}
}
